﻿namespace OMR.Crawler.Core.Crawlers
{
    using System;
    using System.Collections;

    /// <summary>
    /// OMR # 10.08.2012
    /// </summary>
    public class MyCollection : ICollection
    {
        #region Fields

        /// <summary>
        /// Senkronizasyon nesnesidir.
        /// </summary>
        private object _syncLockObj = new object();

        /// <summary>
        /// Asıl koleksiyondur. Bu sınıf tarafından kullanılarak
        /// NameValueCollection tadında bir sınıf tanımlanmış olur.
        /// </summary>
        protected ArrayList InnerList { get; private set; }

        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        public MyCollection()
        {
            this.InnerList = new ArrayList();
        }

        #region Indexers

        /// <summary>
        /// Koleksiyondaki nesneyi indeksine göre döndürür.
        /// </summary>
        /// <example>collection[1]</example>
        /// <param name="index"></param>
        /// <returns></returns>
        public virtual object this[int index]
        {
            get { return GetItem(index); }
            set { SetItem(index, (MyCollectionItem)value); }
        }

        /// <summary>
        /// Koleksiyondaki nesneyi adına göre döndürür.
        /// </summary>
        /// <example>collection["name"]</example>
        /// <param name="name"></param>
        /// <returns></returns>
        public virtual object this[string name]
        {
            get { return GetItem(name); }
            set { SetItem((MyCollectionItem)value); }
        }

        #endregion

        #region AddItem

        /// <summary>
        /// Koleksiyona nesne ekler
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public void Add(string name, string value)
        {
            Add(new MyCollectionItem() { Name = name, Value = value });
        }

        /// <summary>
        /// Koleksiyona nesne ekler
        /// </summary>
        /// <param name="nameValuePair"></param>
        public void Add(MyCollectionItem nameValuePair)
        {
            MyCollectionItem item = GetItem(nameValuePair.Name);

            if (item != null)
            {
                throw new InvalidOperationException("item already exists"); // TODO:
            }

            InnerList.Add(nameValuePair);
        }

        #endregion

        #region Get-Set Items

        /// <summary>
        /// Koleksiyondaki nesneyi indeksine göre döndürür.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public MyCollectionItem GetItem(int index)
        {
            return (MyCollectionItem)InnerList[index];
        }

        /// <summary>
        /// Koleksiyondaki nesneyi adına göre döndürür.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public MyCollectionItem GetItem(string name)
        {
            for (int i = 0; i < Count; i++)
            {
                if (((MyCollectionItem)InnerList[i]).Name == name)
                {
                    return (MyCollectionItem)InnerList[i];
                }
            }

            return null;
        }

        /// <summary>
        /// Koleksiyonun ilgili indeksine
        /// nameValuePair nesnesini atar.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="nameValuePair"></param>
        public void SetItem(int index, MyCollectionItem nameValuePair)
        {
            InnerList[index] = nameValuePair;
        }

        /// <summary>
        /// Koleksiyonun ilgili isimdeki nesnesine
        /// nameValuePair nesnesini atar. Eğer istenilen
        /// isimde bir nesne bulunamazsa yeni nesne eklenir.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="nameValuePair"></param>
        public void SetItem(MyCollectionItem nameValuePair)
        {
            MyCollectionItem item = GetItem(nameValuePair.Name);

            if (item != null)
                item = nameValuePair;

            InnerList.Add(nameValuePair);
        }

        #endregion

        #region ICollection Members

        /// <summary>
        /// ICollection üyesidir. Koleksiyonun başka bir
        /// koleksiyonun istenilen yerine kopyalanmasını
        /// sağlar
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(Array array, int index)
        {
            InnerList.CopyTo(array, index);
        }

        /// <summary>
        /// ICollection üyesidir. Koleksiyondaki nesne sayısını döndürür.
        /// </summary>
        public int Count
        {
            get { return InnerList.Count; }
        }

        /// <summary>
        /// ICollection üyesidir. Koleksiyonun senkronize edilmiş
        /// olma durumunu döndürür.
        /// </summary>
        public bool IsSynchronized
        {
            get { return false; }
        }

        /// <summary>
        /// ICollection üyesidir. Koleksiyonun senkronize edilme
        /// işlemlerinde kullanılacak nesneyi döndürür
        /// </summary>
        public object SyncRoot
        {
            get { return _syncLockObj; }
        }

        #endregion

        #region IEnumerable Members

        /// <summary>
        /// IEnumerable üyesidir. Koleksiyonun sıralı bir şekilde
        /// okunabilmesini sağlar. Aynı zamanda foreach ile kullanım
        /// gibi bazı kolaylıklar *da* sağlar.
        /// </summary>
        /// <returns></returns>
        public IEnumerator GetEnumerator()
        {
            // Sıralama işlemini yapacak sınıfın yeni örneğini döndür.
            return new MyCollectionItemEnumerator(this);
        }

        #endregion
    }

    public class MyCollectionItem
    {
        public string Name { get; set; }

        public object Value { get; set; }
    }

    public class MyCollectionItemEnumerator : IEnumerator
    {
        private int _currentItemIndex = -1;
        private MyCollection _collection;

        public MyCollectionItemEnumerator(MyCollection collection)
        {
            _collection = collection;
        }

        #region IEnumerator Members

        public object Current
        {
            get { return _collection[_currentItemIndex]; }
        }

        public bool MoveNext()
        {
            ++_currentItemIndex;

            return _collection.Count > _currentItemIndex;
        }

        public void Reset()
        {
            _currentItemIndex = -1;
        }

        #endregion
    }
}
